
class LRStavka:
    def __init__(self, lr_stavka):

        self.desna_strana = []
        self.lijeva_strana = [lr_stavka[0]]
        self.desna_strana.extend(lr_stavka[1:])
       
        indeks = lr_stavka.index('*')
        
        self.ispred_tocke = lr_stavka[1:indeks]
        self.iza_tocke = lr_stavka[indeks+1:]

        self.lista_zapocinje = "TBD"


class Generator:
    def __init__(self):
        self.nezavrsni_znakovi=[]
        self.zavrsni_znakovi=[]
        self.znakovi=[]
        self.sinkronizacijski_znakovi=[]
        self.produkcije={}
        self.red_produkcija=[]
        self.pocetni=""
        self.prazni_znakovi=set([])
        self.tablica=set()
        self.lr_stavke=dict()


    def citaj(self):
        datoteka=open("ulaz.txt","r")

        temp=datoteka.readline()
        temp=temp.split()
        self.nezavrsni_znakovi=temp[1:]
        self.pocetni=self.nezavrsni_znakovi[0]
        temp=datoteka.readline()
        temp=temp.split()
        self.zavrsni_znakovi=temp[1:]
        self.znakovi.extend(self.zavrsni_znakovi)
        self.znakovi.extend(self.nezavrsni_znakovi)

        temp=datoteka.readline()
        temp=temp.split()
        self.sinkronizacijski_znakovi=temp[1:]


        for line in datoteka:
            if line[0]=="<":
                zadnji=line.strip()

            else:
                if zadnji in self.produkcije:
                    self.produkcije[zadnji].append(line.strip())
                    self.red_produkcija.append(zadnji +"->"+ line.strip())

                else:
                    self.produkcije[zadnji]=[line.strip()]
                    self.red_produkcija.append(zadnji +"-"+ line.strip())


    def dodaj_pocetni(self):
        pocetni="<PNZ>"
        i=0
        while pocetni in self.produkcije:
            pocetni="<"+"PNZ"+i*"_"+">"
            i=i+1
        self.produkcije[pocetni]=[self.pocetni]
        self.pocetni=pocetni


    def izracunaj_prazne(self):
        temp_prazni_znakovi=set([])
        prvi=1
        while(self.prazni_znakovi != temp_prazni_znakovi or prvi==1):
            prvi=0
            self.prazni_znakovi=temp_prazni_znakovi.copy()
            for i in self.produkcije:
                for j in self.produkcije[i]:
                    znakovi_produkcije=j.split()
                    if znakovi_produkcije[0]=="$":
                        temp_prazni_znakovi.add(i)
                    else:
                        svi_prazni=1
                        for znak in znakovi_produkcije:
                            if znak not in temp_prazni_znakovi:
                                svi_prazni=0

                        if svi_prazni==1:
                            temp_prazni_znakovi.add(i)


    def zapocinje_izravno_znakom(self):
        for i in self.nezavrsni_znakovi:
            if i not in self.produkcije.keys():
                continue
            for j in self.znakovi:
                for k in self.produkcije[i]:
                    znakovi = k.split()
                    for l in znakovi:
                        if l == j:
                            self.tablica.add((i, j))
                        if l not in self.prazni_znakovi:
                            break


    def zapocinje_znakom(self):
        tablica2 = self.tablica.copy()
        ulazak = 1
        while self.tablica != tablica2 or ulazak:
            ulazak = 0
            self.tablica = tablica2.copy()
            for i in self.tablica:
                for j in self.tablica:
                    if i == j or i[1] != j[0]:
                        continue

                    for k in self.tablica:
                        if k[0]==j[0]:
                            tablica2.add((i[0], k[1]))
                            promijenjeno = 1


    def dodaj_tocke(self):
        for i in self.produkcije.items():
            self.lr_stavke[i[0]] = []
            for j in i[1]:
                znakovi = j.split()
                if znakovi == ['$']:
                    tmp = ['*']
                    self.lr_stavke[i[0]].append(tmp)
                else:
                    for k in range(0, len(znakovi)+1):
                        tmp = list(znakovi)
                        tmp.insert(k, '*')
                        self.lr_stavke[i[0]].append(tmp)


    def vrati_lr_stavke(self):
        stavke = []
        for i in self.lr_stavke.items():
            for j in i[1]:
                stavke.append(LRStavka([i[0]]+j))
        return stavke


def main():
    test=[]
    a=Generator()
    a.citaj()
#    a.dodaj_pocetni()
    a.izracunaj_prazne()
    a.zapocinje_izravno_znakom()
    a.zapocinje_znakom()
    a.dodaj_tocke()
    lr_stavke = a.vrati_lr_stavke()
    for n in lr_stavke:
        print(n.lijeva_strana, n.desna_strana)
        print(n.ispred_tocke)
        print(n.iza_tocke)



if __name__ == "__main__": main()

